Install Bootstrap 4 on a Rails 6 App with Webpacker
I know many existing tutorials explain how to install Bootstrap 4 on a Rails 6 application with Webpacker (like the GoRails example). However, I wanted to create this tutorial to highlight a few gotchas, as well as highlight why and how I made some of my choices.
rails new rails-bootstrap
yarn add bootstrap jquery popper.js
-
Add jQuery and Popper.js plugins. These are required by Bootstrap.
This step was always so cryptic to me. I would just blindly copy and paste what I saw on other tutorials, but I wanted to know how people knew to even do this.
I found this example in the Webpacker docs, so decided to use it knowing it was in the official documentation.
// config/webpack/environment.js const { environment } = require("@rails/webpacker"); const webpack = require("webpack"); environment.plugins.prepend( "Provide", new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery", jquery: "jquery", "window.jQuery": "jquery", Popper: ["popper.js", "default"], }) ); module.exports = environment;
Another big problem I ran into was how to correctly import Bootstrap’s styles.
I initially created
app/javascript/packs/application.scss
and imported the styles in that file. However, that seemed to break my build in a way that made it soapp/javascript/packs/application.js
never compiled.Next, I renamed
app/assets/stylesheets/application.css
toapp/assets/stylesheets/application.scss
, and imported the styles into that file. That worked, but it meant that the Asset Pipeline was responsible for my styles. This isn’t necessarily a bad thing, but I wanted Webpacker to be responsible for all of my front-end code.Also, by using a
.scss
file, you can easily override Bootstrap’s default variales mkdir app/javascript/
touch app/javascript/stylesheets/application.scss
-
Import Bootstrap Styles
// app/javascript/stylesheets/application.scss @import "~bootstrap/scss/bootstrap";
-
Import Bootstrap, load styles, and optionally load Tooltips and Popovers everywhere.
// app/javascript/packs/application.js require("bootstrap"); import "../stylesheets/application"; document.addEventListener("turbolinks:load", function () { $(function () { $('[data-toggle="tooltip"]').tooltip(); $('[data-toggle="popover"]').popover(); }); });
Webpacker emits css files only if
extract_css
is set totrue
inwebpacker.yml
otherwisestylesheet_pack_tag
returns nil.When I was running through these steps, I found it strange that I didn’t need to add a stylesheet_pack_tag as I had seen in other tutorials. I realized that this is because I was in development.
If you change
extract_css: false
toextract_css: true
under thedefault:
block inconfig/webpacker.yml
and then restart your server, you’ll notice that the styles no longer load. -
To fix this, simply add the
stylesheet_pack_tag
and restart the server. After ensuring the styles haves loaded setextract_css: true
back toextract_css: false
under thedefault:
block inconfig/webpacker.yml
. You might need to runrails webpacker:clobber
after making that change.<%# app/views/layouts/application.html.erb %> <!DOCTYPE html> <html> <head> <title>RailsBootstrap4Integration</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%# ℹ️ Add stylesheet_pack_tag %> <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <div class="container"> <%= yield %> </div> </body> </html>
-
Finally, add the responsive meta tag
<%# app/views/layouts/application.html.erb %> <!DOCTYPE html> <html> <head> <title>RailsBootstrap4Integration</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%# ℹ️ Add a responsive meta tag %> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <div class="container"> <%= yield %> </div> </body> </html>